/*
    处理注册请求的cgi接口
*/
#include <iostream>
#include<sstream>
#include <mysql/mysql.h>
#include <unistd.h>
#include <string>
#include "common.hpp"
#include <jsoncpp/json/json.h>
#define NOT_STD -1
#define SQL_CON_ERR -4
#define QUERY_ERR -5
#define RES_ERR -6
#define PARSE_JSON_ERR -7
#define REGISTER_ERR -2
using namespace std;

string token;//定义全局
string user_id;
// 通过method来获取参数的方法
bool getQueryString(std::string &query)
{
    std::string method;
    method = getenv("METHOD");
    if ("GET" == method)
    {
        // 不对get请求处理
        return false;
    }
    else if ("POST" == method)
    {

        // POST方法参数通过管道传
        if (getenv("CONTENT_LENGTH") == NULL)
        {
            std::cerr << "获取正文长度参数失败!!!" << std::endl;
            return false;
        }
        int len = atoi(getenv("CONTENT_LENGTH"));
        // std::cerr<<"DEBUG:"<<len<<std::endl;
        char ch;
        while (len)
        {
            ssize_t n = read(0, &ch, 1);
            if (n > 0)
            {
                query.push_back(ch);
                len--;
            }
            else
            {
                return false;
            }
        }
        std::cerr << "DEBUG: 读取正文参数成功!!" << std::endl;
        return true;
    }
    return false;
}

// 校验登陆用户名密码,对表进行查询
int mysql_register(const std::string &name, const std::string &pwd)
{
    stringstream ss;
    // 检查密码是否符合规范
    if (name.size() == 0 || pwd.size()<6)
    {
        std::cerr<<"密码或用户名不规范!!"<<std::endl;
        return NOT_STD;

    }

    MYSQL *conn = mysql_init(nullptr);
    if (nullptr == mysql_real_connect(conn, "127.0.0.1", "ldcwd", "123456", "httptest", 3306, nullptr, 0))
    {
        std::cerr << " mysql connect error !!" << std::endl;
        return SQL_CON_ERR;
    }
        std::cerr << " mysql connect success !!" << std::endl;

    // 验证用户名
    std::string sql = "select * from users where name = \'" + name + "\';"; //
    if (mysql_query(conn, sql.c_str()))
    {
        // 查询失败
        std::cerr << "查询失败" << std::endl;
        return QUERY_ERR;
    }
    // 把结果提取到结果集中再对用户名进行校验
    MYSQL_RES *res = mysql_store_result(conn);
    if (res != NULL)
    {
        // 提取成功

        int fields = mysql_num_fields(res); // 2.获取列

        // 获取内容行对应的char**
        MYSQL_ROW row_content = mysql_fetch_row(res);
        if (row_content == nullptr)
        {
        std::cerr << " 用户不存在可注册 !!" << std::endl;

            //进行插入用户操作
            string regist_sql="insert into users(name,password) values(\'"+name+"\',\'"+pwd+"\');";
        std::cerr << "DEBUG: 插入语句:"<<regist_sql << std::endl;

           if( mysql_query(conn,regist_sql.c_str()))
           {
            //插入失败
            return REGISTER_ERR;
           }
        std::cerr << " 注册成功!!!" << std::endl;
//-------------------------更新sessions表---------------------------------
           //插入成功,获取用户信息
           ss<<"select *from users where name= "<<"\'"<<name<<"\'"<<";";
           cerr<<"DEBUG: SQL: "<<ss.str()<<endl;
           if(mysql_query(conn,ss.str().c_str()))
           {
            return QUERY_ERR;
           }
           //清空sql命令
           ss.str("");
           //提取查询结果
          MYSQL_RES* res= mysql_store_result(conn);
          if(res==nullptr)
          {
            return RES_ERR;
          }
          //获取列
          int fields=mysql_num_fields(res);
          //获取行内容
          MYSQL_ROW row_conent=mysql_fetch_row(res);
          //获取userid
           user_id=row_conent[0];
          //获取username
            string user_name=row_conent[1];
        //生成token
            token=AuthMiddleware::generate_random_token(user_id);
            //存入数据库并设置过期时间

            ss<<"insert into sessions(user_id,token,expires_at) values("\
            <<user_id<<","<<"\'"<<token<<"\'"<<","<<"DATE_ADD(NOW(),INTERVAL 1 DAY)"<<");";
          cerr<<"DEBUG: SQL: "<<ss.str()<<endl;
           if( mysql_query(conn,ss.str().c_str()))
           {
            return QUERY_ERR;
           }
//-------------------------------更新sessions---  end----------------------------------------
           return 0;
        }
        else
        {
            //结果集不为空说明有存在同名用户
            return REGISTER_ERR;
        }

        // //遍历打印
        //  for(int i=0;i<fields;i++)
        // {
        //     std::cerr<<fields_arr[i].name<<"\t";
        // }
        // std::cerr<<std::endl;

        // for(int i=0;i<fields;i++)
        // {
        //     std::cerr<<row[i]<<"\t";
        // }
        // std::cerr<<std::endl;
    }
    else
    {
        // 提取失败
        std::cerr << "ERROR: 提取结果集失败!!" << std::endl;
        return RES_ERR;
    }
    mysql_free_result(res);
    mysql_close(conn);
    return 0;
}

// 通过返回码code构建一个可返回的string
std::string buildString(const int &code)
{
    std::string ret;
    // 注册成功返回 success url token
    Json::Value v; // 万能对象结构体
    switch (code)
    {
    case 0:
        // 把对应的键值对写入 万能对象结构体
        v["success"] = true;
        v["url"] = "http://47.99.68.28:8888/blog/blog_html/blog_home.html"; // 这里的url需要写全吗?
        v["message"] = "注册成功!!";
        v["token"]=token;
        v["user_id"]=user_id;
        break;
    case NOT_STD:
        v["success"] = false;
        v["message"] = "密码或用户名不规范!请输入6~12位密码";
        break;
    case REGISTER_ERR:
         v["success"] = false;
        v["message"] = "注册失败!!!";
        break;
    case QUERY_ERR:
        v["success"] = false;
        v["message"] = "指令错误!!!";
        break;
    case SQL_CON_ERR:
        v["success"] = false;
        v["message"] = "连接错误!!!";
        break;
    case RES_ERR:
        v["success"] = false;
        v["message"] = "结果集错误!!!";
        break;
    }
    // 序列化JSON得到一个串
    Json::StyledWriter w;
    ret = w.write(v);
    return ret;
}
int main()
{
    // std::cout<<mysql_get_client_info()<<std::endl;
    // 1.获取参数
    std::string query_string;
    if (getQueryString(query_string))
    {
        std::cerr << "DEBUG: 解析前json字符串:  " << query_string << std::endl;

        // 对json字符串进行解析(反序列化)
        Json::Value v;
        Json::Reader r;
        bool success = r.parse(query_string, v);
        std::string name;
        std::string pwd;
        if (success)
        {
            name = v["username"].asString();
            pwd = v["userpwd"].asString();
        }
        else
        {
            // 解析失败
            std::cerr << "json ERROR!" << std::endl;
            return PARSE_JSON_ERR;
        }

        int n = mysql_register(name, pwd);
        std::string ret = buildString(n);

        // 直接向标准输出流输出(已被管道文件重定向)
        std::cout << ret;
    }
    else
    {
        // 获取参数失败
        return -1;
    }
    return 0;
}